<template>
    <div ref="editContainer" class="code-editor" :style="{ height: h }" ></div>
</template>
<script>
import { getCurrentInstance, onMounted, watch } from 'vue';
import * as monaco from 'monaco-editor/esm/vs/editor/editor.main.js';
import JsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker';
// 解决vite Monaco提示错误
self.MonacoEnvironment = {
    getWorker() {
        return new JsonWorker();
    },
};
export default {
    props: {
        value: String,
        language: String,
        h: String,
        lines: Array,
    },
    setup(props, { emit }) {
        let monacoEditor = null;
        const { proxy } = getCurrentInstance();
        if (!props.language) {
            props.language = 'json';
        }
        if (!props.h) {
            props.h = '200px';
        }

        watch(
            () => props.value,
            (value) => {
                // 防止改变编辑器内容时光标重定向
                if (value !== monacoEditor?.getValue()) {
                    monacoEditor.setValue(value);
                }
            },
        );

        watch(
            () => props.language,
            (language) => {
                if (language !== monacoEditor?.getModel().getLanguageId()) {
                    monaco.editor.setModelLanguage(
                        monacoEditor.getModel(),
                        props.language
                    );
                    monacoEditor.setValue(props.value);
                }
            },
        );

        onMounted(() => {
            monacoEditor = monaco.editor.create(proxy.$refs.editContainer, {
                value: props.value,
                readOnly: false,
                language: props.language,
                theme: 'vs-dark',
                automaticLayout: true, //自动布局
                selectOnLineNumbers: true,
                renderSideBySide: false,
            });

            monacoEditor.onDidChangeModelLanguage(() => {
                console.log("语言改变")
            });

            // 监听值变化
            monacoEditor.onDidChangeModelContent(() => {
                const currenValue = monacoEditor?.getValue();
                emit('update:value', currenValue);
            });

            function highlightLines(editor, lineNumbers) {
                var decorations = lineNumbers.map(lineNumber => {
                    var line = editor.getModel().getLineContent(lineNumber);
                    var lineStartModel = editor.getModel().getPositionAt(editor.getModel().getOffsetAt({ lineNumber: lineNumber, column: 1 }));
                    var lineEndModel = editor.getModel().getPositionAt(editor.getModel().getOffsetAt({ lineNumber: lineNumber, column: line.length + 1 }));
                    var range = {
                        startLineNumber: lineStartModel.lineNumber,
                        startColumn: lineStartModel.column,
                        endLineNumber: lineEndModel.lineNumber,
                        endColumn: lineEndModel.column
                    };
                    return {
                        range: range,
                        options: {
                            isWholeLine: true,
                            className: 'highlighted-line',
                            glyphMarginClassName: 'highlighted-gutter-line',
                        }
                    };
                });

                // 创建装饰器
                var decorationIds = editor.deltaDecorations([], decorations);

                // 在编辑器关闭时移除装饰器
                editor.onDidDispose(() => {
                    editor.deltaDecorations(decorationIds, []);
                });
            }

            if (props.lines && props.lines.length) {
                // 高亮显示第2行和第5行
                highlightLines(monacoEditor, props.lines);
            }


        });
        return {
            h: props.h,
        };
    },
};
</script>
<style scoped>
.code-editor {
    width: 100%;
    min-height: 200px;
    position: relative;
}
</style>


